package top.zhangjianyong.tools.timer;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import top.zhangjianyong.tools.annotation.DoTimer;
import top.zhangjianyong.tools.entity.RemindItem;
import top.zhangjianyong.tools.remind.RemindStrategyHolder;
import top.zhangjianyong.tools.remind.strategy.RemindStrategy;
import top.zhangjianyong.tools.service.mybatis.IHolidayService;
import top.zhangjianyong.tools.service.mybatis.IRemindItemService;
import top.zhangjianyong.tools.utils.ExceptionUtil;
import top.zhangjianyong.tools.utils.MailUtil;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author ： zhangjianyong
 * @date ： 2021/11/1 下午8:16
 */
@Slf4j
@Component
public class ClockInRemindTimer {

    @Autowired
    private IHolidayService iHolidayService;
    @Autowired
    private IRemindItemService iRemindItemService;
    @Autowired
    private RemindStrategyHolder remindStrategyHolder;
    @Value("${reset-url}")
    private String RESET_URL;
    @Value("${timer-flag}")
    private Boolean timerFlag;

    //一分钟执行一次
    @Scheduled(cron = "0 */1 * * * ?")
    @DoTimer
    public void remind() {
        log.info("进入提醒。。。。");
        List<RemindItem> list = iRemindItemService.listByState("未确认");
        list.forEach(remindItem -> {

            try {
                remind(remindItem);
            } catch (Exception e) {
                //保存失败信息
                iRemindItemService.saveErrorMessage(remindItem.getId(), e.getMessage());
                log.error(e.getMessage(), e);
            }
        });
    }

    private void remind(RemindItem remindItem) throws Exception {
        log.info("开始提醒");
        log.info(JSONObject.toJSONString(remindItem));
        String remindDay = remindItem.getRemindType();
        String state = remindItem.getState();
        LocalDateTime remindTime = remindItem.getRemindTime();

        LocalDateTime now = LocalDateTime.now();
        if ("未确认".equals(state) && now.isAfter(remindTime)) {
            log.info("到达提醒时间");
            RemindStrategy strategy = remindStrategyHolder.getStrategy(remindDay);
            if (strategy == null) {
                log.info("未配置策略 {}", remindDay);
                MailUtil.send("605600162@qq.com",
                        "警告：未查询到提醒配置 " + ",时间：" + LocalDateTime.now(),
                        "未查询到提醒配置，" + remindDay);
            } else {
                strategy.remind(remindItem);
            }

        }

    }


    //每天零点
    @Scheduled(cron = "0 0 0 * * ?")
    @DoTimer
    public void reset() throws Exception {
        log.info("零点重置提醒。。。");
        boolean notify = true;
        List<Exception> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            try {
                log.info("开始第" + i + "次重置");
                List<String> types = remindStrategyHolder.resetType();
                for (String type : types) {
                    iRemindItemService.reset(type);
                }
                notify = false;
                log.info("重置成功");

                break;
            } catch (Exception e) {
                list.add(e);
                Thread.currentThread().sleep(60 * 1000);
                log.error(e.getMessage(), e);
            }
        }


        if (notify) {
            log.info("重置失败，开始通知");

            StringBuilder sb = new StringBuilder();
            sb.append("手动重置: ").append(RESET_URL).append("\n");
            String collect = list.stream()
                    .map(ExceptionUtil::getExceptionToString)
                    .collect(Collectors.joining());
            sb.append("报错:").append("\n").append(collect);
            MailUtil.send("605600162@qq.com",
                    "警告：零点重置提醒任务失败，请检查！！！" + ",时间：" + LocalDateTime.now(),
                    sb.toString());
        }

    }
}
